package com.thiswhyme.common.utils.json.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.thiswhyme.common.expection.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * @description: Json工具-Jackson
 * @author: thiswhyme
 * @date: 2021/8/31
 */
@Slf4j
public class JacksonUtils {

    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        //忽略 在json字符串中存在，但是在java对象中不存在对应属性的情况。防止错误
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 对象转json
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> String obj2String(T obj){
        if (obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("对象转json失败", e);
            throw new BusinessException("对象转json失败");
        }
    }

    /**
     * 对象转json，并格式化的输出
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> String obj2StringPretty(T obj){
        if (obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("对象转json失败", e);
            throw new BusinessException("对象转json失败");
        }
    }

    /**
     * json转对象
     * @param json
     * @param clazz
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T string2Obj(String json, Class<T> clazz){
        if (StringUtils.isEmpty(json) || clazz == null){
            return null;
        }
        try {
            return clazz.equals(String.class)? (T)json : objectMapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            log.error("json转对象失败", e);
            throw new BusinessException("json转对象失败");
        }
    }

    /**
     * json转对象
     * @param json
     * @param typeReference
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T string2Obj(String json, TypeReference<T> typeReference){
        if(StringUtils.isEmpty(json) || typeReference == null){
            return null;
        }
        try {
            return (T)(typeReference.getType().equals(String.class)? json : objectMapper.readValue(json,typeReference));
        } catch (JsonProcessingException e) {
            log.error("json转对象失败", e);
            throw new BusinessException("json转对象失败");
        }
    }
}
